﻿/// <reference path="../../jquery/jquery-1.10.2.min.js" />
/// <reference path="../../Common.js" />

/// <reference path="../linqInJavaScript.js" />


/*用于呈现多选或单选框
 * 2017-07-11 徐东强创建
 * 
 */



(function ($) {
    var fn = $.fn;
    fn.checkgroup = function (options, ischeckbox) {
        /// <summary>组合选项</summary>
        var t = this;
        function _click() {
            var t = this, $t = $(t), $c = $t.parent().parent(), opt = $c.data("options");
            if ($.isTrue(opt.ischeckbox)) {
                if ($t.hasClass("checked")) {
                    $t.removeClass("checked");
                }
                else {
                    $t.addClass("checked");
                }
            }
            else {
                $c.find(".checked").removeClass("checked");
                $t.addClass("checked");
            }
            var val = _getValue(opt.$container);
            opt.$input.val(val).trigger("change");
            opt.$container.trigger("change");
        };
        function _onHiddenChange() {
            /// <summary>隐藏域变更事件</summary>
            var $t = $(this);
            var newVal = $t.val()
            , $container = $t.parent()
            , arr = _getValue($container)
            , options = $container.data("options")
            , expired = typeof (arr) == "string" ? arr : JSON.stringify(arr)
            , ischeckbox = $.isTrue(options.ischeckbox)
            ;
            if (newVal != expired) {
                var newArr = [];
                if (ischeckbox) {
                    if (newVal) {
                        if ($.isArray(newVal)) {
                            newArr = newArr.concat(newVal);
                        }
                        else {
                            newArr = eval("({0})".format(newVal));
                        }
                    }
                    else {
                        newVal = [];
                    }
                    for (var i = 0; i < newArr.length; i++) {
                        newArr[i] = newArr[i].toString();
                    }
                }
                else {
                    newArr.push(newVal);
                }
                $container.find(".check-box")
                .each(function () {
                    var $t = $(this), val = $t.val().toString();
                    if (newArr.indexOf(val) >= 0)
                        $t.addClass("checked");
                    else
                        $t.removeClass("checked");
                });
                $container.val(newArr);
            }
        };

        function _getValue($container) {
            var val = [];
            $container.find(".checked")
            .each(function () {
                var v = $(this).val().toString();
                val.push(v);
            });
            $container.val(val);
            var opt = $container.data("options");
            if ($.isTrue(opt.ischeckbox)) {
                return val;
            }
            else {
                return val.length ? val[0] : "";
            }
        }
        t.each(function () {
            var t = this, $t = $(t);
            if (!$t.is("div"))
                return alert("checkgroup必须使用div作为容器");
            var opt = $t
                .addClass('check-group')
            .data();
            if (ischeckbox !== undefined) {
                opt.ischeckbox = ischeckbox;
            }
            opt.$container = $t;
            opt.$input = $("<input type='hidden'/>").change(_onHiddenChange);
            if (opt.attrs) {
                if (typeof (opt.attrs) == "string") {
                    opt.attrs = eval("(" + opt.attrs + ")");
                }
                opt.$input.attr(opt.attrs);
            }
            if (opt.events) {
                if (typeof (opt.events) == "string") {
                    opt.events = eval("(" + opt.events + ")");
                }
                var myEvents = ["blur", "focus", "click", "dbclick", "mouseenter", "mousemove", "change"];
                for (var x in opt.events) {
                    var act = opt.events[x];
                    if (myEvents.indexOf(x) >= 0 && typeof (act) == "function") {
                        opt.$input.on(x, act);
                    }
                }
            }
            if (!opt.$input.attr("id") && !opt.$input.attr("name")) {
                opt.$input.attr({
                    id: opt.$container.attr("id")
                    , name: opt.$container.attr("name")
                })
            };
            opt.$options = $("<div/>").addClass("options-container");
            $t.append(opt.$input).append(opt.$options);
            if (options && options.length) {
                opt.items = options;
            } else if (!opt.items) {
                opt.items = [];
            }
            if (typeof (opt.items) == "string") {
                opt.item = eval("(" + opt.items + ")");
            }
            var val = $t.val() || [];
            for (var i = 0; i < opt.items.length; i++) {
                var it = opt.items[i];
                var $op = $("<span/>")
                .addClass("check-box")
                .html(it.key)
                .attr("data-value", it.value)
                .click(_click);
                if (it.checked || val.indexOf(it.value) >= 0) {
                    $op.addClass("checked");
                    it.checked = true;
                }
                opt.$options.append($op);
            };
            opt.$container.data("options", opt);
            var newVal = _getValue(opt.$container);
            opt.$input.val(newVal);
        });
        return t;
    };


    //hook jquery.val

    var expiredDiv = $.valHooks.div;

    $.valHooks.div = {
        get: function (ele, par) {
            var $ele = $(ele), tagName = $ele[0].tagName.toLowerCase();
            if ($ele.is(".check-group")) {
                var val = [];
                $ele.find(".options-container")
                .find(".checked")
                .each(function () {
                    var $t = $(this);
                    val.push({ "key": $t.text(), "value": $t.data("value") });
                });
                var ret = val.select(function (x) {
                    return x.value;
                }).join(",");
                if (ret.indexOf('"') == 0) {
                    ret = ret.substring(1);
                    ret = ret.substring(0, ret.length - 1);
                };
                return ret;
            }
            else {
                switch (tagName) {
                    case "div":
                        if (expiredDiv)
                            return expiredDiv.get.apply(this, arguments);
                    case "textarea":
                        return $ele.html();
                    default:
                        if ($ele.data("value") !== undefined) {
                            return $ele.data("value");
                        }
                        else {
                            var _delegate = $.valHooks[tagName];
                            if (_delegate && _delegate != $.valHooks.div)
                                return _delegate.get.apply(this, arguments);
                            return "";
                        }
                }
            }
        }
        , set: function (ele, val) {
            var $ele = $(ele), tagName = $ele[0].tagName.toLowerCase(), _tp = typeof (val);
            if ($ele.is(".check-group")) {
                if (typeof (val) == "string") {
                    val = val.split(",");
                }
                $ele.find(".checked").removeClass("checked");
                for (var i = 0; i < val.length; i++) {
                    var v = val[i];
                    if (v === null || v === undefined)
                        v = "";
                    else if (v && v.indexOf("[") == 0)
                        v = JSON.parse(v)[0];
                    try {
                        $ele
                            .find("[data-value={0}]".format(v))
                         .addClass("checked");
                    } catch (e) {
                        debugger;
                    }
                }
            }
            else {
                switch (tagName) {
                    case "div":
                        if (expiredDiv)
                            return expiredDiv.set.apply(this, arguments);
                        break;
                    case "textarea":
                        $ele.html(val);
                        break;
                    default:
                        var _delegate = $.valHooks[tagName];
                        if (_delegate && _delegate != $.valHooks.div) {
                            return _delegate.set.apply(this, arguments);
                        }
                        else {
                            return $ele.data("value", val);
                        }
                }
            }
        }
    };
    $.valHooks.textarea = $.valHooks.a = $.valHooks.span = $.valHooks.li = $.valHooks.ul = $.valHooks.div;
    $.valHooks.input = {
        get: function (ele, par) {
            var $ele = $(ele);
            if ($ele.is("[type=checkbox],[type=radio]")) {
                var name = $ele.attr("name");
                if (name)
                    $ele = $("input[name={0}]".format(name));
                var val = [];
                $ele.each(function () {
                    var $t = $(this), chk = $t.prop("checked"), value = $t.prop("value");
                    if (chk)
                        val.push(value);
                });
                return val.join(",");
            }
            else if ($ele.is("[type=file]")) {
                //input[file]不能直接用修改value，否则会抛出异常！
                return $ele.prop("value") || $ele.data("value");
            }
            else if ($ele.data("value") !== undefined) {
                return $ele.data("value");
            }
            else {
                return $ele.prop("value");
            }
        }
            , set: function (ele, val) {
                var $ele = $(ele), _tp = typeof (val);
                for (var i = 0; i < val.length; i++) {
                    val[i] = val[i] == null ? "" : val[i].toString();
                }
                if ($ele.is("[type=checkbox],[type=radio]")) {
                    var name = $ele.attr("name");
                    if (name)
                        $ele = $("input[name={0}]".format(name));
                    $ele.each(function () {
                        var $t = $(this), value = $t.prop("value").toString();
                        $t.prop("checked", val.indexOf(value) >= 0);
                    });
                    return val.join(",");
                }
                else if ($ele.is("[type=file]")) {
                    //input[file]不能直接用修改value，否则会抛出异常！
                    return $ele.data("value", val);
                }
                else if (_tp != "boolean" && _tp != "string") {
                    var newVal = null;
                    if (val === null) newVal = "";
                    else newVal = JSON.stringify(val);
                    return $ele.data("value", val) && $ele.prop("value", newVal);
                }
                else {
                    return $ele.prop("value", val);
                }
            }
    }
    $.valHooks.radio = $.valHooks.checkbox = $.valHooks.input;
    $(function () {
        $(".check-group")
            .each(function () {
                if ($(this).children("input:hidden").length)
                    return;
                $(this).checkgroup();
            });
    });

    var expiredVal = $.prototype.val;
    $.prototype.val = function (a) {
        if (a == undefined) {
            return expiredVal.apply(this, arguments);
        }
        //jQuery会将数组转成字符串！而其他对象则不会！
        if ($.isArray(a)) {
            expiredVal.call(this, a);
            return this.data("value", a);
        }
        else {
            return expiredVal.apply(this, arguments);
        }
    };
})(jQuery);